﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Speech.Recognition;
using System.Speech.AudioFormat;
using System.IO;
using System.Windows;




namespace Supply_Fetch.MUILayer
{

    public delegate void SpeechEventHandler( Item fItem );


    /// <summary>
    /// The Speech To Text Engine class consists of the necessary functionalities to use the Recognition Engine provided by the System.Speech namespace.
    /// It is designed specifically for the Supply Fetch.
    /// 
    /// *Note to self: come up with better class definition.
    /// </summary>
    class SpeechToTextEngine
    {

        private SpeechRecognitionEngine speechRecognizer;
        public event SpeechEventHandler speechEventHandler;
        private bool speechRecognized;
        private string wordStr;
        private float confidenceStr;

        /// <summary>
        /// Constructor sets up the speech to text engine for use. Note: remove grammar preload later.
        /// </summary>
        /// <param name="grammar">This is the grammar of words the Speech to Text Engine can recognize.</param>
        public SpeechToTextEngine()
        {

            speechRecognizer = new SpeechRecognitionEngine(new System.Globalization.CultureInfo("en-US"));

            try
            {
                speechRecognizer.SetInputToDefaultAudioDevice();
            }
            catch (InvalidOperationException e)
            {
                var msBox = MessageBox.Show("Please connect or reconnect the Microphone", "Microphone not connected error", MessageBoxButton.OK, MessageBoxImage.Error);
                //Environment.Exit(0);
            }

            speechRecognizer.SpeechRecognized += new EventHandler<SpeechRecognizedEventArgs>(recognizer_SpeechRecognized);
            speechRecognized = false;
        }

        /// <summary>
        /// This method updates the grammar of the speech to text engine during runtime.
        /// </summary>
        /// <param name="items">A listing of all the items in the system.</param>
        public void UpdateDictionary(string[] items)
        {
            this.speechRecognizer.UnloadAllGrammars();

            this.speechRecognizer.LoadGrammarAsync(new Grammar(new GrammarBuilder(new Choices(items))));
        }

        /// <summary>
        /// This method activates the Speech to Text engine to start listening for voice commands.
        /// </summary>
        public void ActivateListenMode()
        {
            //RecognitionResult result = speechRecognizer.Recognize(TimeSpan.FromSeconds(8));
            speechRecognized = false;
            this.speechRecognizer.RecognizeAsync(RecognizeMode.Multiple);
        }

        public void DeactivateListenMode()
        {
            speechRecognized = false;
            this.speechRecognizer.RecognizeAsyncStop();
        }

        /// <summary>
        /// Event handler for the speech recognized event this notifies event subscribers outside class that an event occured.
        /// </summary>
        /// <param name="sender">Generic data type containing general info about event thrown.</param>
        /// <param name="e">Generic data type that contains more specific info about event thrown; more importantly contain word that was recognized.</param>
        public void recognizer_SpeechRecognized(object sender, SpeechRecognizedEventArgs e)
        {
            speechRecognized = true;
            if (e.Result == null) {
                wordStr = "UNKNOWN";
            }
            else {
                wordStr = e.Result.Text;
                confidenceStr = e.Result.Confidence;
            }
            
            this.speechRecognizer.RecognizeAsyncStop();       
        }

        public string WordStr
        {
            get { return wordStr; }
        }

        public float ConfidenceVal
        {
            get { return confidenceStr; }
        }

        public bool SpeechRecognized
        {
            get { return speechRecognized; }
        }
    }
}
